﻿using Sgr.Exceptions;

namespace Sgr.Application.Queries
{
    /// <summary>
    /// 查询辅助类，主要处理组织ID相关的查询逻辑
    /// </summary>
    public static class QueryHelper
    {
        /// <summary>
        /// 获取当前用户的用户ID
        /// </summary>
        /// <param name="currentUser">当前用户信息接口</param>
        /// <returns>当前用户的用户ID</returns>
        /// <exception cref="ArgumentNullException">当前用户信息为空时抛出</exception>
        /// <exception cref="BusinessException">无法获取有效的用户ID时抛出</exception>
        /// <remarks>
        /// 此方法主要用于：
        /// 1. 验证当前用户信息是否存在
        /// 2. 确保能够获取到有效的用户ID
        /// 3. 转换用户ID从字符串到长整型
        /// </remarks>
        public static long GetUserId(ICurrentUser currentUser)
        {
            // 确保当前用户信息不为空
            Check.NotNull(currentUser, nameof(currentUser), "当前用户信息不能为空");

            // 尝试解析并验证用户ID
            if (!long.TryParse(currentUser.Id, out long userId) || userId <= 0)
                throw new BusinessException("无法获取当前用户标识，请确保用户已登录或用户信息正确。");

            return userId;
        }

        /// <summary>
        /// 获取当前用户所属的组织ID
        /// </summary>
        /// <param name="currentUser">当前用户信息接口</param>
        /// <returns>当前用户的组织ID</returns>
        /// <exception cref="ArgumentNullException">当前用户信息为空时抛出</exception>
        /// <exception cref="BusinessException">无法获取有效的组织ID时抛出</exception>
        /// <remarks>
        /// 此方法主要用于：
        /// 1. 验证当前用户信息是否存在
        /// 2. 确保能够获取到有效的组织ID
        /// 3. 转换组织ID从字符串到长整型
        /// </remarks>
        public static long GetOrgId(ICurrentUser currentUser)
        {
            // 确保当前用户信息不为空
            Check.NotNull(currentUser, nameof(currentUser), "当前用户信息不能为空");

            // 尝试解析并验证组织ID
            if (!long.TryParse(currentUser.OrgId, out long orgId) || orgId <= 0)
                throw new BusinessException("无法获取当前组织标识，请确保用户已登录或组织信息正确。");

            return orgId;
        }

        /// <summary>
        /// 根据请求参数获取实际要查询的组织ID
        /// </summary>
        /// <param name="currentUser">当前用户信息接口</param>
        /// <param name="request">请求中指定的组织ID（可选）</param>
        /// <returns>最终要查询的组织ID</returns>
        /// <remarks>
        /// 此方法实现了以下业务规则：
        /// 1. 默认使用当前用户所属的组织ID
        /// 2. 如果当前用户是超级管理员（组织ID为1），且请求中指定了其他组织ID，则使用请求中的组织ID
        /// 3. 普通用户只能查询自己所属组织的数据
        ///
        /// 使用场景：
        /// - 在需要支持跨组织查询的接口中使用
        /// - 处理超级管理员的特殊查询权限
        /// </remarks>
        public static long GetOrgId(ICurrentUser currentUser, long? request)
        {
            // 获取当前用户的组织ID
            long currentOrgId = GetOrgId(currentUser);

            // 如果是超级管理员且请求中指定了有效的组织ID，则使用请求中的组织ID
            if (request.HasValue && request.Value > 0 && currentOrgId == Constant.SUPER_ADMIN_ORG_ID)
                currentOrgId = request.Value;

            return currentOrgId;
        }

        /// <summary>
        /// 获取当前用户的租户ID；若缺失则抛出 <see cref="UnauthorizedAccessException"/>。
        /// 方法语义为“获取必须存在的租户标识（否则中止操作）”。
        /// </summary>
        /// <param name="currentUser">当前用户信息</param>
        /// <returns>租户 ID（long）</returns>
        /// <exception cref="ArgumentNullException">currentUser 为 null 时抛出</exception>
        /// <exception cref="UnauthorizedAccessException">当前用户缺少租户信息时抛出</exception>
        public static long GetRequiredTenantId(ICurrentUser currentUser)
        {
            Check.NotNull(currentUser, nameof(currentUser), "当前用户信息不能为空");

            return currentUser.TenantId
                ?? throw new UnauthorizedAccessException("当前用户缺少租户信息，无法执行此操作");
        }
    }
}